Thread: char myarray[0] in struct

  1. #1
    Registered User
    Join Date
    Dec 2008
    Posts
    32

    char myarray[0] in struct

    I know this topic is in the usenet C FAQ, but they just offer a one-sentence answer saying it's not strictly in adherence to the standard but not much else, so here goes:

    I was given an API for some network-based stuff and the header was littered with things like: (this is overly simplified)

    Code:
    #pragma pack(push,1)
    typedef struct {
      unsigned long packetid;
      unsigned char data[0]; 
    } packet_t;
    #pragma pack(pop)
    Fortunately my compiler understood the pragma. It did NOT, however, like the empty array.

    I had never seen anything like this before. And so like an idiot my first instict was to just change it to (unsigned char*), yeah bad idea... now I see why they did it that way. (Well maybe I do?)

    No, actually I don't understand, now that I've just typed that. Assuming he's the just victim of memcpy() calls, there are a billion other ways to handle that without such things, yes? Worst case you've got a "&" in each call. Anyway that's a side issue and not my real question.

    The problem stems from the fact that the actual implementation contains sizeof(packet_t) _everywhere_. And from reading the code it seems that the zero-length array must not take up any space.

    So my question is quite simply what is the easiest way to fix this?

    What I ended up doing was changing the struct member to data[1] and then unfortunately I had to go through and find every instance ot sizeof(packet_t) and replace it with sizeof(packet_t) - 1. Actually not a literal "-1", but rather a constant using many FOUR_LETTER_WORDS which gets eval'd as (-1). Everywhere in the darn code, and since it wasn't just one struct I had a lot of reading to do.

    This worked. Or seemed to. With such a kludgy solution I can't help but wonder if I missed that one place, and the thing will crash/hang if exactly one fewer bytes comes in off the wire.

    Is there a better way that doesn't depend on compiler-specific tricks?

    Especially keeping in mind the company's next version of the API will likely contain the same kind of thing and I'll have to do it all again? Something oh I dunno like:

    Code:
    #pragma humor_me_guys   sizeof(packet_t) = sizeof(packet_t)-1
    (half-joking), or perhaps a creative use of a union which is portable? Anything.

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> Actually not a literal "-1", but rather a constant...
    I like that idea.
    Code:
    #define packet_hdr_sz (sizeof(packet_t) - 1) /* $%&^ stupid @$$ $%!& */
    gg

  3. #3
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    In C99 this was legalized (look up "struct hack") -- you can put an [] in place of the [0]; sizeof will not report any room for that last "array".

  4. #4
    Registered User
    Join Date
    Dec 2008
    Posts
    32
    Wow, had no clue they legalized that. Thanks, that was just the magic solution I was looking for! I don't know if my old 2002 compiler is fully C99 compliant but it didn't complain about the [], so as long as sizeof() comes out ok I think I'm golden.

    Thanks again.

  5. #5
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Well sizeof isn't going to work, because sizeof doesn't know what the hell you're talking about. What you're doing is faking the size of the block of memory you're allocating. You do something like:
    Code:
    struct foo *ptr = sizeof( *ptr ) + bytesforarray;
    If you use sizeof, it's still going to only see it as the size of the structure.


    Quzah.
    Hope is the first step on the road to disappointment.

  6. #6
    Registered User
    Join Date
    Dec 2008
    Posts
    32
    Quote Originally Posted by quzah View Post
    If you use sizeof, it's still going to only see it as the size of the structure.
    Yes, I know, and that's the goal!

    The whole point is sizeof() needs to report the size of the struct _without_ that last "dummy" member. My problem was no matter what I did I was adding 1 byte, or 4. depending on what I tried. The empty[] did the trick fine.

    (The size of the actual data written "past the end" is obviously handled elsewhere. Hey, I didnt' write the stuff, I just have to get it compiled.)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. memory issue
    By t014y in forum C Programming
    Replies: 2
    Last Post: 02-21-2009, 12:37 AM
  2. Link List math
    By t014y in forum C Programming
    Replies: 17
    Last Post: 02-20-2009, 06:55 PM
  3. Another syntax error
    By caldeira in forum C Programming
    Replies: 31
    Last Post: 09-05-2008, 01:01 AM
  4. Contest Results - May 27, 2002
    By ygfperson in forum A Brief History of Cprogramming.com
    Replies: 18
    Last Post: 06-18-2002, 01:27 PM
  5. How do you search & sort an array?
    By sketchit in forum C Programming
    Replies: 30
    Last Post: 11-03-2001, 05:26 PM